import os
from ast import literal_eval
from projs.models import *
from utils.decorators import admin_auth
from django.http import JsonResponse
from django.conf import settings
from .models import *
from django.http import StreamingHttpResponse
from django.db.models import Q,F,Count
import datetime
import uuid
from django.shortcuts import render
import re
from pure_pagination import Paginator,PageNotAnInteger
import itertools
import collections
from django import forms
from dss.Serializer import serializer
import json
import time
from django.db.models.query import Prefetch
import xlsxwriter
from django.contrib.auth.decorators import permission_required

import datetime
from django.shortcuts import render
from projs.models import *
from users.models import UserProfile
from assets.models import Assets, ServerAssets
from utils.decorators import admin_auth, deploy_auth
from projs.utils.git_tools import GitTools
from projs.utils.svn_tools import SVNTools
from fort.models import FortServerUser


def find_product_name(request):
    if request.method == 'GET':
        product_name = request.GET.get('product_name', False)
        if product_name:
            product = ProjectProduct.objects.filter(product_name__icontains=product_name)
            results = [{'id': i.id, 'text': i.product_name} for i in product]
        else:
            results = []
        return JsonResponse({'code': 200, 'results': results})

def get_monday_sunday(now=0):
    monday = datetime.date.today() - datetime.timedelta(days=datetime.date.today().weekday()) - datetime.timedelta(days=7*now)
    sunday = monday + datetime.timedelta(days=6)
    return (monday,sunday)


def find_inventory_context(request):
    try:
        today_date = time.strftime('%Y-%m-%d')
        today_product_count = AppInventory.objects.filter(product_date = today_date).count()
        year_count = AppInventory.objects.filter(product_date__year=datetime.date.today().year, display='0').count()
        month_count = AppInventory.objects.filter(product_date__month=datetime.date.today().month, display='0').count()
        week_count = AppInventory.objects.filter(product_date__range=get_monday_sunday(now=0), display='0').count()
        context = {
                   'today_product_count': today_product_count,
                   'month_count': month_count,
                   'year_count': year_count,
                   'week_count': week_count,
                   }
        return JsonResponse({"code":200, "context": context})
    except:
        return JsonResponse({"code":500})



def get_inventory_info(request):
    if request.method == "GET":
        page = request.GET.get('page')  # how many items per page
        page_size = request.GET.get('page_size')  # how many items in total in the DB
        order = request.GET.get('ordering')  # ascending or descending
        filter = json.loads(request.GET.get('filter','{}'))
        setup = json.loads(request.GET.get('setup','{}'))
        multi_sort = json.loads(request.GET.get('multiSort','{}'))
        all_records = AppInventory.objects.filter(display='0')
        if setup['delay'] == '1':
            all_records = all_records.filter(delay = '1')
        else:
            if setup['delay'] == '2':
                delay_records = all_records.filter(delay = '1')
            all_records = all_records.filter(delay = '0')
            if setup.get('product_date_start',None):
                all_records = all_records.filter(product_date__gte = datetime.datetime.strptime(setup['product_date_start'],'%Y-%m-%d'))
            if setup.get('product_date_end',None):
                all_records = all_records.filter(product_date__lte = datetime.datetime.strptime(setup['product_date_end'],'%Y-%m-%d'))
            if setup['delay'] == '2':
                all_records = all_records|delay_records
        all_records = all_records.filter(department_id__name__contains = filter.pop('department',''),system_id__product_name__contains = filter.pop('system',''),name__contains = filter.pop('name',''),submitter__contains = filter.pop('submitter',''),tester__contains = filter.pop('tester',''))
        if filter.get('urgent',None):
            all_records = all_records.filter(urgent = filter['urgent'])
        if filter.get('deploy',None):
            all_records = all_records.filter(deploy = filter['deploy'])
        if filter.get('confirmation',None):
            all_records = all_records.filter(confirmation = filter['confirmation'])
        if filter.get('process',None):
            all_records = all_records.filter(process = filter['process'])
        if filter.get('version',None):
            all_records = all_records.filter(version__contains = filter['version'])
        if filter.get('product_no',None):
            all_records = all_records.filter(product_no__contains = filter['product_no'])
        if filter.get('trade_method',None):
            all_records = all_records.filter(trade_method__contains = filter['trade_method'])
        all_records = all_records.order_by('-create_time')
        if order:  # 判断是否有排序需求
            all_records = all_records.order_by(order)
        for sort_option in multi_sort:
            all_records = all_records.order_by(sort_option['sortOrder']+sort_option['sortName'])
        all_records_count = all_records.count()
        if not page or page == 'NaN':
            page = 1
        if not page_size:
            page_size = 10
        if page_size == 'UNLIMITED':
            page_size = all_records_count
        pageinator = Paginator(all_records, int(page_size))  # 开始做分页
        response_data = {'total': all_records_count, 'rows': []}  # 必须带有rows和total这2个key，total表示总页数，rows表示每行的内容
        for asset in pageinator.page(page).object_list:
            response_data['rows'].append({
                "id": asset.id if asset.id else "",
                "department": AppDepartment.objects.get(id=asset.department_id).name if asset.department_id else "",
                "confirmation": asset.confirmation if asset.confirmation else "0",
                "system": ProjectProduct.objects.get(id=asset.system_id).product_name if asset.system_id else "",
                "version": asset.version if asset.version else "",
                "name": asset.name if asset.name else "",
                "product_date": asset.product_date.strftime("%Y-%m-%d") if asset.product_date else "",
                "create_time": asset.create_time.strftime("%Y-%m-%d %H:%M:%S") if asset.create_time else "",
                "content": asset.content if asset.content else "",
                "product_no": asset.product_no if asset.product_no else "",
                "submitter": asset.submitter if asset.submitter else "",
                "checker": asset.checker if asset.checker else "",
                "trade": asset.trade if asset.trade else "",
                "tester": asset.tester if asset.tester else "",
                "process": asset.process if asset.process else "0",
                "deploy": asset.deploy if asset.deploy else "0",
                "description": asset.description if asset.description else "",
                "delay": asset.delay if asset.delay else "0",
                "urgent": asset.urgent if asset.urgent else "0",
                "trade_method": asset.trade_method if asset.trade_method else "0",
                "trade_content": asset.trade_content if asset.trade_content else "",
                })
        return JsonResponse(response_data)



def get_change_info(request):
    if request.method == "GET":
        name_id = request.GET.get('nameId')
        all_records = AppChange.objects.filter(name_id=name_id).filter(display='0')
        response_data = {'total': all_records.count(), 'rows': []}
        for asset in all_records:
            response_data['rows'].append({
                "id": asset.id if asset.id else "",
                "reason": asset.reason if asset.reason else "",
                "create_time": asset.create_time.strftime('%Y-%m-%d %H:%M:%S') if asset.create_time else "",
                })
        return JsonResponse(response_data)



def get_inventory_list(request):
    if request.method == "GET":
        context = {
            'department': AppDepartment.objects.all(),
            'system': ProjectProduct.objects.all(),
        }
        return render(request,'projs/inventorylist.html',context)

def find_user_permission(user):
    #0 管理者 1 外协 2 其他
    if user.is_superuser or user.has_perm('projs.admin_appinventory'):
        return '0'
    elif user.has_perm('projs.test_appinventory'):
        return '1'
    else:
        return '2'

def get_inventory_form(request):
    group = find_user_permission(request.user)
    if request.method == 'GET':
        instance = AppInventory.objects.filter(id=request.GET.get('id',None)).filter(display='0').values()
        if len(instance) > 0:
            output = instance[0]
            output['department']=output.pop('department_id')
            output['system']=output.pop('system_id')
            return JsonResponse(serializer(output, output_type='json'),safe=False)
        else:
            return JsonResponse({"errors":'相关记录不存在!'})
    if request.method == 'POST':
        #data = json.loads(request.body)
        if group == '2':
            return JsonResponse({"errors":'你没有相应权限!'})
        data = request.POST
        data._mutable = True
        try:
            instance = AppInventory.objects.get(id=data.get('id',None))
            if instance.display == '1':
                return JsonResponse({"errors":'相关记录不存在!'})
            if data.get('batch',False):
                try:
                    field = data.get('field',None)
                    value = data.get('value',None)
                    if group == '1' and field not in ('version', 'product_no', 'tester', 'process', 'description'):
                        return JsonResponse({"errors":'你没有相应权限!'})
                    if field == 'product_date':
                        if re.compile(r'\d{4}-\d{1,2}-\d{1,2}').search(value):
                            try:
                                datetime.datetime.strptime(value,'%Y-%m-%d')
                                instance.delay = '0'
                            except:
                                return JsonResponse({"errors":'保存失败!'})
                        else:
                            if len(value) == 0:
                                value = None
                                instance.delay = '1'
                            else:
                                return JsonResponse({"errors":'保存失败!'})
                    setattr(instance,field,value)
                    instance.save()
                    return JsonResponse({"message":'success'})
                except:
                    return JsonResponse({"errors":'保存失败!'})
            form = AppInventoryForm(data, instance=instance)
            if not form.is_valid():
                return JsonResponse({"form_errors":form.errors})
            else:
                instance.save()
                return JsonResponse({"message":'success'})
        except:
            if group != '0':
                return JsonResponse({"errors":'你没有相应权限!'})
            data.update({'display': '0'})
            form = AppInventoryForm(data)
            if not form.is_valid():
                return JsonResponse({"form_errors":form.errors})
            else:
                inventory = AppInventory.objects.create(department=AppDepartment.objects.get(id=data['department']),
                                                        confirmation=data['confirmation'],
                                                        system=ProjectProduct.objects.get(id=data['system']),
                                                        version=data['version'],
                                                        name=data['name'],
                                                        product_date=datetime.datetime.strptime(data['product_date'],'%Y-%m-%d') if data['product_date'] else None,
                                                        product_no=data['product_no'],
                                                        submitter=data['submitter'],
                                                        trade=data['trade'],
                                                        content=data['content'],
                                                        tester=data['tester'],
                                                        checker=data['checker'],
                                                        process=data['process'],
                                                        deploy=data['deploy'],
                                                        description=data['description'],
                                                        delay=data['delay'],
                                                        urgent=data['urgent'],
                                                        display='0',
                                                        repo=data['repo'],
                                                        repo_model=data['repo_model'],
                                                        trade_content=data['trade_content'],
                                                        trade_method=data['trade_method']
                                                        )
                inventory.save()
                return JsonResponse({"message":'success'})


def delete_inventory_info(request):
    group = find_user_permission(request.user)
    if group != '0':
        return JsonResponse({"errors":'你没有相应权限!'})
    if request.method == 'POST':
        try:
            instance = AppInventory.objects.get(id=request.GET.get('id',None))
            instance.display = '1'
            instance.save()
            return JsonResponse({"message":'success'})
        except:
            return JsonResponse({"errors":'相关记录不存在!'})


class AppInventoryForm(forms.ModelForm):

    class Meta:
        model = AppInventory
        fields = "__all__"

    def clean(self):
        cleaned_data = super(AppInventoryForm,self).clean()
        _ = ['name','version','product_no','tester','description']
        for condition in _:
            old = cleaned_data.get(condition,None)
            if old and re.compile(r'[\s\"]').search(old):
                self.add_error(condition,'包含了符号"与空格,请修改')
        return cleaned_data


def get_appchange_form(request):
    if request.method == 'GET':
        instance = AppChange.objects.filter(id=request.GET.get('id',None)).filter(display='0').values()
        if len(instance) > 0:
            output = instance[0]
            output['name']=AppInventory.objects.get(id=output['name_id_id']).name
            output['name_id']=output.pop('name_id_id')
            return JsonResponse(serializer(output, output_type='json'),safe=False)
        else:
            return JsonResponse({"errors":'相关记录不存在!'})
    if request.method == 'POST':
        #data = json.loads(request.body)
        group = find_user_permission(request.user)
        if group != '0':
            return JsonResponse({"errors":'你没有相应权限!'})
        data = request.POST
        try:
            inventory = AppInventory.objects.get(id=data.get('name_id',None))
            if inventory.display == '1':
                return JsonResponse({"errors":'相关记录不存在!', "type":1})
        except:
            return JsonResponse({"errors":'相关记录不存在!', "type":1})
        try:
            instance = AppChange.objects.get(id=data.get('id',None))
            if instance.display == '1':
                return JsonResponse({"errors":'相关二次变更记录不存在!', "type":0})
            form = AppChangeForm(data, instance=instance)
        except:
            if inventory.product_date is not None and datetime.date.today() > inventory.product_date:
                return JsonResponse({"errors":'该项目已投产,不能登记二次变更,请确认!', "type":0})
            data._mutable = True
            data.update({'display': '0'})
            form = AppChangeForm(data)
        if not form.is_valid():
            return JsonResponse({"form_errors":form.errors})
        else:
            form.save()
            return JsonResponse({"message":'success'})


def delete_change_info(request):
    if request.method == 'POST':
        group = find_user_permission(request.user)
        if group != '0':
            return JsonResponse({"errors":'你没有相应权限!'})
        try:
            instance = AppChange.objects.get(id=request.GET.get('id',None))
            instance.display = '1'
            instance.save()
            return JsonResponse({"message":'success'})
        except:
            return JsonResponse({"errors":'相关记录不存在!'})


class AppChangeForm(forms.ModelForm):

    class Meta:
        model = AppChange
        fields = "__all__"


def get_inventory_statistic(request):
    if request.method == "GET":
        context = {'system': ProjectProduct.objects.all()}
        return render(request, 'projs/inventorystatistic.html', context)



def get_recent_inventory(request):
    if request.method == "POST":
       setup = json.loads(request.body)
       if not setup.get('system', None):
            setup['system'] = []
       result=[]
       for i in range(12):
            inventory_count = AppInventory.objects.filter(display='0', product_date__range=get_monday_sunday(now=i), system_id__in=setup['system']).count()
            try:
                range_date = get_monday_sunday(now=i)
                changes_count = AppChange.objects.filter(name_id__display='0', name_id__product_date__range=range_date, name_id__system_id__in=setup['system']).filter(display='0', create_time__date__lte=range_date[1]).count()
            except:
                changes_count = 0
            result.append({'week_num': i,'inventory_count': inventory_count,'changes_count': changes_count})
       return JsonResponse(result,safe=False)


def inventory_statistic_info(request):
    if request.method == "GET":
        setup = json.loads(request.GET.get('setup','{}'))
        all_records = AppInventory.objects.filter(display='0')
        if not setup.get('system', None):
            setup['system'] = []
        if setup.get('product_date_start',None) and setup.get('product_date_end',None):
            all_records = all_records.filter(product_date__gte = datetime.datetime.strptime(setup['product_date_start'],'%Y-%m-%d'))
            all_records = all_records.filter(product_date__lte = datetime.datetime.strptime(setup['product_date_end'],'%Y-%m-%d'))
        else:
            return JsonResponse({"errors":'请输入检索时间范围!'})
        all_records = all_records.filter(system_id__in=setup['system']).order_by('system_id')
        try:
            #all_changes = AppChange.objects.prefetch_related(Prefetch('name_id',queryset=all_records)).filter(create_time__date__range=(datetime.datetime.strptime(setup['product_date_start'],'%Y-%m-%d'),datetime.datetime.strptime(setup['product_date_end'],'%Y-%m-%d')))
            all_changes = AppChange.objects.filter(name_id__display='0', name_id__product_date__range=(datetime.datetime.strptime(setup['product_date_start'],'%Y-%m-%d'), datetime.datetime.strptime(setup['product_date_end'],'%Y-%m-%d')), name_id__system_id__in=setup['system']).filter(display='0', create_time__date__lte=datetime.datetime.strptime(setup['product_date_end'],'%Y-%m-%d'))
            all_changes = all_changes.annotate(system_id=F('name_id__system')).values('system_id').annotate(change=Count('system_id'))
        except:
            all_changes = []
        total_records = all_records.values('system_id').annotate(total=Count('system_id'))
        formal_records = all_records.filter(urgent='0').values('system_id').annotate(formal=Count('system_id'))
        emergency_records = all_records.filter(urgent='1').values('system_id').annotate(emergency=Count('system_id'))
        flexible_records = all_records.filter(urgent='2').values('system_id').annotate(flexible=Count('system_id'))
        results = list(map(lambda x: dict(x,**{'formal':0,'emergency':0,'flexible':0,
                                              'change': 0,
                                              'system': ProjectProduct.objects.get(id=x['system_id']).product_name}) ,total_records))
        from itertools import chain
        for combine in list(chain(formal_records,emergency_records,flexible_records,all_changes)):
            for result in results:
                if combine['system_id'] == result['system_id']:
                    result.update(combine)
                    break
        response_data = {'total': len(results), 'rows': results}  # 必须带有rows和total这2个key，total表示总页数，rows表示每行的内容
        return JsonResponse(response_data)

def download_response(filepath):
    """
        to download files
    """
    def file_iterator(filepath, chunk_size=262144):
        with open(filepath, 'rb') as f:
            while True:
                c = f.read(chunk_size)
                if c:
                    yield c
                else:
                    break

    response = StreamingHttpResponse(file_iterator(filepath),
                                     content_type='application/octet-stream; charset=UTF-8')  # application/vnd.ms-excel
    response['Content-Disposition'] = 'attachment;filename="%s"' % (os.path.basename(filepath))
    response['Content-Length'] = os.path.getsize(filepath)
    return response


def download_change_info(request):
    if request.method == "GET":
        tmp_dir = os.path.join(os.path.join(settings.BASE_DIR,'media'),'tmp')
        if not os.path.exists(tmp_dir):
            os.mkdir(tmp_dir)
        filepath = os.path.join(tmp_dir,str(uuid.uuid1()).replace('-','')+'.xlsx')
        start_date = request.GET.get('start_date',None)
        end_date = request.GET.get('end_date',None)
        if not start_date and not end_date:
            return JsonResponse({"errors":'检索时间范围不能为空!'})
        result = AppChange.objects.filter(display='0', create_time__range=(datetime.datetime.strptime(start_date,'%Y-%m-%d'), datetime.datetime.strptime(end_date,'%Y-%m-%d')),name_id__display='0').order_by('name_id','create_time')
        workbook = xlsxwriter.Workbook(filepath)
        try:
            worksheet = workbook.add_worksheet(u'变更明细')
            title = workbook.add_format({'bold': True,'align':'center','valign':'vcenter','bg_color':'#007ee5','border':1})
            content = workbook.add_format({'text_wrap':True,'align':'center','valign':'vcenter','border':1})
            time = workbook.add_format({'text_wrap':True,'align':'center','valign':'vcenter','num_format':'yyyy-mm-dd h:mm:ss','border':1})
            worksheet.set_column(0,0,5)
            worksheet.set_column(1,1,15)
            worksheet.set_column(2,2,60)
            worksheet.set_column(3,3,100)
            worksheet.set_column(4,4,20)
            row0 = [u'序号',u'系统',u'上线单名称',u'原因',u'修改时间']
            for r in range(len(row0)):
                worksheet.write(0, r, row0[r], title)
            i = 1
            worksheet.freeze_panes(1,0)
            worksheet.autofilter('B1:C1')
            for change in result:
                worksheet.write(i, 0, i,content)
                worksheet.write_string(i, 1, change.name_id.system.product_name,content)
                worksheet.write_string(i, 2, change.name_id.name,content)
                worksheet.write_string(i, 3, change.reason,content)
                worksheet.write_datetime(i, 4, change.create_time,time)
                i += 1
            workbook.close()
        except:
            workbook.close()
        response = download_response(filepath)
        return response

def _upload(file, filename):
    try:
        f = open(filename, "wb")
        for chunk in file.chunks():
            f.write(chunk)
        f.close()
        return True
    except Exception as e:
        print(str(e))
        return False



def download_inventory_info(request):
    if request.method == "GET":
        tmp_dir = os.path.join(os.path.join(settings.BASE_DIR, 'media'), 'tmp')
        if not os.path.exists(tmp_dir):
            os.mkdir(tmp_dir)
        filepath = os.path.join(tmp_dir, str(uuid.uuid1()).replace('-', '') + '.xlsx')
        start_date = request.GET.get('start_date',None)
        end_date = request.GET.get('end_date',None)
        if not start_date and not end_date:
            return JsonResponse({"errors":'检索时间范围不能为空!'})
        result = AppInventory.objects.filter(product_date__range=(datetime.datetime.strptime(start_date,'%Y-%m-%d'), datetime.datetime.strptime(end_date,'%Y-%m-%d')),display='0').order_by('product_date','name')
        workbook = xlsxwriter.Workbook(filepath)
        try:
            worksheet = workbook.add_worksheet(u'测试跟踪单')
            title = workbook.add_format({'bold': True,'align':'center','valign':'vcenter','bg_color':'#007ee5','border':1,})
            content = workbook.add_format({'text_wrap':True,'align':'center','valign':'vcenter','border':1,})
            time = workbook.add_format({'text_wrap':True,'align':'center','valign':'vcenter','num_format':'yyyy-mm-dd','border':1,})
            worksheet.set_column(0,0,8)
            worksheet.set_column(1,1,12)
            worksheet.set_column(2,2,15)
            worksheet.set_column(3,3,35)
            worksheet.set_column(4,4,13)
            worksheet.set_column(5,5,25)
            worksheet.set_column(6,6,15)
            worksheet.set_column(7,7,15)
            worksheet.set_column(8,8,15)
            worksheet.set_column(9,9,20)
            worksheet.set_column(10,10,15)
            worksheet.set_column(11,11,18)
            worksheet.set_column(12,12,17)
            worksheet.set_column(13,13,15)
            worksheet.set_column(14,14,10)
            worksheet.set_column(15,15,12)
            worksheet.set_column(16,16,12)
            worksheet.set_column(17,17,15)
            worksheet.set_column(18,18,13)
            row = [u'序号',u'提出部门',u'系统',u'上线单名称',u'上线时间',u'内容',u'涉及交易',u'上线单类型',u'验证方式',u'验证交易',u'版本库情况',u'变更单版本编号',u'运维变更单号',u'上线单提交人',u'复核人','测试人员','测试进度','备注','创建日期']
            for r in range(len(row)):
                worksheet.write(0, r, row[r], title)
            i = 1
            worksheet.freeze_panes(1,0)
            worksheet.autofilter('A1:S1')
            for inv in result:
                worksheet.set_row(i, 30)
                worksheet.write(i, 0, inv.id, content)
                worksheet.write_string(i, 1, inv.department.name, content)
                worksheet.write_string(i, 2, inv.system.product_name, content)
                worksheet.write_string(i, 3, inv.name, content)
                worksheet.write_datetime(i, 4, inv.product_date, time)
                worksheet.write_string(i, 5, inv.content if inv.content else '', content)
                worksheet.write_string(i, 6, inv.trade if inv.trade else '', content)
                worksheet.write(i, 7, dict(inv.urgent_choice)[inv.urgent], content)
                worksheet.data_validation(i, 7, i, 7, {'validate': 'list', 'source': list(dict(inv.urgent_choice).values())})
                worksheet.write(i, 8, dict(inv.trade_method_choice)[inv.trade_method], content)
                worksheet.data_validation(i, 8, i, 8, {'validate': 'list', 'source': list(dict(inv.trade_method_choice).values())})
                # worksheet.write(i, 8, dict(inv.deploy_choice)[inv.deploy], content)
                # worksheet.data_validation(i, 8, i, 8, {'validate': 'list', 'source': list(dict(inv.deploy_choice).values())})
                worksheet.write_string(i, 9, inv.trade_content if inv.trade_content else '', content)
                worksheet.write(i, 10, dict(inv.confirmation_choice)[inv.confirmation], content)
                worksheet.data_validation(i, 10, i, 10, {'validate': 'list', 'source': list(dict(inv.confirmation_choice).values())})
                worksheet.write_string(i, 11, inv.version, content)
                worksheet.write_string(i, 12, inv.product_no, content)
                worksheet.write_string(i, 13, inv.submitter, content)
                worksheet.write_string(i, 14, inv.checker, content)
                worksheet.write_string(i, 15, inv.tester, content)
                worksheet.write(i, 16, dict(inv.process_choice)[inv.process], content)
                worksheet.data_validation(i, 16, i, 16, {'validate': 'list', 'source': list(dict(inv.process_choice).values())})
                worksheet.write_string(i, 17, inv.description, content)
                worksheet.write_datetime(i, 18, inv.create_time, time)
                i += 1
            workbook.close()
        except:
            workbook.close()
        response = download_response(filepath)
        return response


@permission_required('projs.view_projectproduct', raise_exception=True)
def get_project_product(request):
    project_product = ProjectProduct.objects.all()
    return render(request, 'projs/projectproductlist.html', locals())



@permission_required('projs.add_project', raise_exception=True)
def proj_list(request):
    projects = Project.objects.select_related('project_admin').all()
    project_envs = Project.project_envs
    project_products = ProjectProduct.objects.all()
    project_users = UserProfile.objects.all()
    return render(request, 'projs/proj_list.html', locals())


@permission_required('projs.add_service', raise_exception=True)
def proj_org(request, pk):
    project_obj = Project.objects.select_related('project_admin').get(id=pk)
    services = Service.objects.select_related('project').filter(project=project_obj)
    assets = Assets.objects.all()
    if request.method == 'GET':
        project_org = project_obj.project_org
        return render(request, 'projs/proj_org.html', locals())
    elif request.method == 'POST':
        try:
            data = request.POST.get('data')
            project_obj.project_org = data
            project_obj.save()
            return JsonResponse({'code': 200, 'msg': '保存成功！'})
        except Exception as e:
            return JsonResponse({'code': 500, 'msg': '保存失败！{}'.format(e)})


@permission_required('projs.add_service', raise_exception=True)
def org_chart(request, pk):
    project_obj = Project.objects.select_related('project_admin').get(id=pk)
    project_org = project_obj.project_org
    return render(request, 'projs/org_chart.html', locals())


@admin_auth
def proj_config(request):
    projects = Project.objects.select_related('project_admin').all()
    repos = ProjectConfig.project_models
    # server_assets = ServerAssets.objects.select_related('assets').all()
    fortserverusers = FortServerUser.objects.filter(fort_server__server_protocol='ssh', fort_user_status=1, fort_server__server_status=1)
    pk = request.GET.get('id')

    if pk:
        return render(request, 'projs/config_detail.html', locals())
    else:
        return render(request, 'projs/proj_config.html', locals())


@permission_required('projs.deploy_project', raise_exception=True)
def config_list(request):
    user = request.user
    projects = user.proj_admin.all() | user.proj_member.all()
    configs = ProjectConfig.objects.select_related('project').all() if user.is_superuser else \
        [project.projectconfig for project in projects if
         hasattr(project, 'projectconfig') and project.project_env != 'prod']
    return render(request, 'projs/config_list.html', locals())


@deploy_auth
def deploy(request, pk):
    config = ProjectConfig.objects.select_related('project').get(id=pk)
    if request.method == 'GET':
        key = request.GET.get('key', None)
        mode = request.GET.get('mode', 'deploy')
        if config.repo == 'git':
            try:
                git_tool = GitTools(repo_url=config.repo_url, path=config.src_dir, env=config.project.get_project_env_display())
            except:
                return render(request, 'projs/deploy.html', locals())
            if key:
                if key == 'model':
                    try:
                        git_tool.clone(prev_cmds=config.prev_deploy)
                        if config.repo_model == 'branch':
                            branches = git_tool.remote_branches
                            return JsonResponse({'code': 200, 'models': branches, 'msg': '获取成功！'})
                        elif config.repo_model == 'tag':
                            tags = git_tool.tags(versions=config.versions.split(','), mode=mode)
                            return JsonResponse({'code': 200, 'models': tags, 'msg': '获取成功！'})
                    except Exception as e:
                        return JsonResponse({'code': 500, 'msg': '获取失败：{}'.format(e)})
                elif key == 'commit':
                    try:
                        branch = request.GET.get('branch')
                        mode = request.GET.get('mode')
                        if request.GET.get('new_commit'):
                            git_tool.pull(branch)
                        commits = git_tool.get_commits(branch, versions=config.versions.split(','), mode=mode,
                                                       max_count=20)
                        return JsonResponse({'code': 200, 'data': commits, 'msg': '获取成功！'})
                    except Exception as e:
                        return JsonResponse({'code': 500, 'msg': '获取失败：{}'.format(e)})
            else:
                if os.path.exists(git_tool.proj_path):
                    local_branches = git_tool.local_branches
                    local_tags = tags = git_tool.tags(versions=config.versions.split(','), mode=mode)
                return render(request, 'projs/deploy.html', locals())

        elif config.repo == 'svn':
            svn_tool = SVNTools(repo_url=config.repo_url, path=config.src_dir, env=config.project.project_env,
                                username=config.repo_user, password=config.repo_password)
            if key:
                if key == 'model':
                    try:
                        if config.repo_model == 'branch':
                            branches = svn_tool.branches
                            return JsonResponse({'code': 200, 'models': branches, 'msg': '获取成功！'})
                        elif config.repo_model == 'tag':
                            tags = svn_tool.tags(versions=config.versions.split(','), mode=mode)
                            return JsonResponse({'code': 200, 'models': tags, 'msg': '获取成功！'})
                    except Exception as e:
                        return JsonResponse({'code': 500, 'msg': '获取失败：{}'.format(e)})
                elif key == 'commit':
                    branch = request.GET.get('branch')
                    try:
                        if branch == 'trunk':
                            commits = svn_tool.get_commits(versions=config.versions.split(','), mode=mode, limit=30)
                        else:
                            commits = svn_tool.get_commits(versions=config.versions.split(','), repo_model='branch',
                                                           model_name=branch, mode=mode, limit=30)
                        return JsonResponse({'code': 200, 'data': commits, 'msg': '获取成功！'})
                    except Exception as e:
                        return JsonResponse({'code': 500, 'msg': '获取失败：{}'.format(e)})
            else:
                return render(request, 'projs/deploy.html', locals())


@admin_auth
def deploy_log(request):
    pk = request.GET.get('pk')
    start_time = request.GET.get('startTime')
    end_time = request.GET.get('endTime')
    if pk:
        result = literal_eval(DeployLog.objects.get(id=pk).result)
        return JsonResponse({'code': 200, 'result': result})
    elif start_time and end_time:
        new_end_time = datetime.datetime.strptime(end_time, '%Y-%m-%d') + datetime.timedelta(1)
        end_time = new_end_time.strftime('%Y-%m-%d')
        try:
            records = []
            search_records = DeployLog.objects.select_related('project_config').select_related('deploy_user').filter(
                c_time__gt=start_time, c_time__lt=end_time)
            for search_record in search_records:
                record = {
                    'id': search_record.id,
                    'project_name': search_record.project_config.project.project_name,
                    'project_env': search_record.project_config.project.get_project_env_display(),
                    'd_type': search_record.get_d_type_display(),
                    'branch_tag': search_record.branch_tag,
                    'release_name': search_record.release_name[:7],
                    'release_desc': search_record.release_desc,
                    'deploy_user': search_record.deploy_user.username,
                    'c_time': search_record.c_time,
                }
                records.append(record)
            return JsonResponse({'code': 200, 'records': records})
        except Exception as e:
            return JsonResponse({'code': 500, 'error': '查询失败：{}'.format(e)})
    else:
        logs = DeployLog.objects.select_related('project_config').select_related('deploy_user').all()
        return render(request, 'projs/deploy_log.html', locals())


def check_log(request, pk):
    config = ProjectConfig.objects.prefetch_related('deploy_server').get(id=pk)
    server = config.deploy_server.first()
    host = server.assets.asset_management_ip
    port = server.port
    username = server.username
    password = server.password
    return render(request, 'projs/check_log.html',
                  {'host': host, 'port': port, 'username': username, 'password': password})
